// #include <libxml/parser.h>
// #include <libxml/tree.h>
// #include <libssh2.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdatomic.h>
#include <unistd.h>
// #include <libxml/tree.h>
#include "server_xml_concise.h"
#include <string.h>
struct TSNCONF
{
    char entity[30];
    char content[20];
};

struct CI
{
    char clockIdentity[8];
};

struct PortID
{
    struct CI ci[8];
    char content[8];
    int ci_num;
    char tag[20];
};

struct Tunnel
{
    atomic_int tag;
    int error;  // xml请求层、操作层是否符合规范
    char mes[20];  // 消息层(rpc、rpc_reply、notification)
    char m_id[20]; // 消息的序号
    char op[20];   // 操作层，若无则null(get、get-bulk、edit、edit-bulk)
    struct TSNCONF TC[20];
    int TC_num;
    struct PortID PI;
};

struct PortIdentity
{
    uint8_t clockIdentity[8];
    int portNumber;
};

struct TSNConfig
{
    int device_id;
    int gm_flag;
    int port_num;
    int master_port;
    int slave_port;
    int link_delay_measure_period;
    int sync_period;
    int domain_number;
    struct PortIdentity port_identity;
    int mean_link_delay_thrld;
};

void parse_rpc(const char *filename, struct Tunnel *tunnel)
{
    xmlDocPtr doc;                       // xml文件
    xmlNodePtr root, node, Node, entity; // xml文件节点

    // 检查libxml2版本
    LIBXML_TEST_VERSION

    // 解析XML文件
    doc = xmlReadFile(filename, NULL, 0);
    if (doc == NULL)
    {
        fprintf(stderr, "Error: unable to parse file %s\n", filename);
        return;
    }
    tunnel->error = 1;
    // 获取XML文档的根元素
    root = xmlDocGetRootElement(doc);
    if (root == NULL)
    {
        fprintf(stderr, "Error: empty document\n");
        xmlFreeDoc(doc);
        return;
    }

    // 确保根元素是 <rpc>，并且有正确的命名空间
    if (!xmlStrcmp(root->name, (const xmlChar *)"rpc"))
    {
        strcpy(tunnel->mes ,"rpc");
        printf("\nhh\n");
    }
    else
    {
        strcpy(tunnel->mes , "erorr"); // 网管只能发rpc给网元，如果消息层是其他消息，则必然是xml文件编写问题
    }

    // 查找message-id 属性
    xmlChar *message_id = xmlGetProp(root, (const xmlChar *)"message-id");
    if (message_id != NULL)
    {   
        memset(tunnel->m_id,0,sizeof(tunnel->m_id));
       strcpy(tunnel->m_id , message_id) ;
    }
    else
    {
        strcpy(tunnel->m_id , "error");
    }

    // 查找操作和内容
    node = root->xmlChildrenNode;
    int i = -1, j = -1;
    while (node != NULL)
    {
        if (node->type == XML_ELEMENT_NODE && xmlStrEqual(node->name, (const xmlChar *)"edit-bulk"))
        {
            strcpy(tunnel->op , "edit-bulk");
            tunnel->error = 0;
            // 查找内容层
            Node = node->xmlChildrenNode;
            while (Node != NULL)
            {
                if (Node->type == XML_ELEMENT_NODE)
                {

                    if (!xmlStrcmp(Node->name, (const xmlChar *)"TSNCONF"))
                    {
                        entity = Node->xmlChildrenNode;
                        while (entity != NULL)
                        {

                            if (entity->type == XML_ELEMENT_NODE)
                            {
                                i++;
                                printf("clockidentify=%d\n",i);
                                if (!xmlStrcmp(entity->name, (const xmlChar *)"device_id"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "device_id");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"gm_flag"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "gm_flag");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"port_num"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "port_num");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"master_port"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "master_port");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"slave_port"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "slave_port");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"link_delay_measure_period"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "link_delay_measure_period");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"sync_period"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "sync_period");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"domain_number"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "domain_number");
                                    strcpy(tunnel->TC[i].content , content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"mean_link_delay_thrld"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->TC[i].entity , "mean_link_delay_thrld");
                                    strcpy(tunnel->TC[i].content , content);
                                }                              
                                else
                                {
                                    strcpy(tunnel->TC[i].entity , "this_entity");
                                    strcpy(tunnel->TC[i].content , "error");
                                }
                            }
                            entity = entity->next;
                        }
                    }
                    else if (!xmlStrcmp(Node->name, (const xmlChar *)"PortID"))
                    {
                        entity = Node->xmlChildrenNode;
                        strcpy(tunnel->PI.tag , "OK");
                        while (entity != NULL)
                        {

                            if (entity->type == XML_ELEMENT_NODE)
                            {
                                if (!xmlStrcmp(entity->name, (const xmlChar *)"clockIdentity"))
                                {
                                    j++;
                                    const xmlChar *content = xmlNodeGetContent(entity);

                                    strcpy(tunnel->PI.ci[j].clockIdentity, content);
                                }
                                else if (!xmlStrcmp(entity->name, (const xmlChar *)"portNumber"))
                                {

                                    const xmlChar *content = xmlNodeGetContent(entity);
                                    strcpy(tunnel->PI.content, content);
                                }
                                else
                                {
                                    strcpy(tunnel->PI.tag , "error");
                                }
                            }
                            entity = entity->next;
                        }
                    }
                }
                Node = Node->next;
            }
        }
        node = node->next;
    }
    tunnel->TC_num = i + 1; // 记录下要读写的内容数
    printf("num=%d\n",tunnel->TC_num);
    tunnel->PI.ci_num = j + 1;
    // xmlFreeDoc(doc);
    // xmlCleanupParser();
}

void write_TSNConfig(struct TSNConfig *tsnconfig, struct Tunnel *tunnel)
{
    int i = 0;
    printf("2");
    for (; i < tunnel->TC_num; i++)
    {
        if (!strcmp(tunnel->TC[i].entity, "device_id"))
        {
            tsnconfig->device_id = atoi(tunnel->TC[i].content);
            strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "gm_flag"))
        {
            tsnconfig->gm_flag = atoi(tunnel->TC[i].content);
           strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "port_num"))
        {
            tsnconfig->port_num = atoi(tunnel->TC[i].content);
            strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "master_port"))
        {
            tsnconfig->master_port = atoi(tunnel->TC[i].content);
            strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "slave_port"))
        {
            tsnconfig->slave_port = atoi(tunnel->TC[i].content);
            strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "link_delay_measure_period"))
        {
            tsnconfig->link_delay_measure_period = atoi(tunnel->TC[i].content);
           strcpy( tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "sync_period"))
        {
            tsnconfig->sync_period = atoi(tunnel->TC[i].content);
            strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "domain_number"))
        {
            tsnconfig->domain_number = atoi(tunnel->TC[i].content);
           strcpy(tunnel->TC[i].content , "OK");
        }
        else if (!strcmp(tunnel->TC[i].entity, "mean_link_delay_thrld"))
        {
            tsnconfig->mean_link_delay_thrld = atoi(tunnel->TC[i].content);
            strcpy(tunnel->TC[i].content , "OK");
        }
        else
        {
            strcpy(tunnel->TC[i].content , "error");
        }
    }
    int j = 0;
    for (; j < tunnel->PI.ci_num; j++)
    {
        tsnconfig->port_identity.clockIdentity[j] = atoi(tunnel->PI.ci[j].clockIdentity);
    }
    if (tunnel->PI.content != NULL)
    {
        tsnconfig->port_identity.portNumber = atoi(tunnel->PI.content);
    }
}